package com.lyc.common.aop;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.multipart.MultipartFile;

import com.lyc.common.annotate.SystemLog;
import com.lyc.common.constants.DepartCommonConstant;
import com.lyc.common.exception.DepartException;
import com.lyc.common.holder.UserContextHolder;
import lombok.extern.slf4j.Slf4j;

/**
 * 记录日志的AOP
 * @Author 李大神仙
 * @Date 2024/2/28 21:49
 * @Version 1.0
 */
/*@Slf4j
@Aspect
@Component
@ConditionalOnClass({ HttpServletRequest.class, RequestContextHolder.class })
public class LogAspect {
    *//**
     * 统计请求的处理时间
     *//*
    ThreadLocal<Long> startTime = new ThreadLocal<>();

    *//**
     * 日志服务
     *//*
    private final SystemLogRecordService logService;

    private static final String FALSE = "false";

    public LogAspect(SystemLogRecordService logService) {
        this.logService = logService;
    }

    *//**
     * 设置操作日志切入点，记录操作日志，在注解的位置切入代码(就是额外新增一种功能)
     *//*
    @Pointcut("@annotation(io.swagger.annotations.ApiOperation)")
    public void logPointCut(){
    }

    @Pointcut("@annotation(org.springframework.web.bind.annotation.RestController)")
    public void controllerPointCut(){
    }

    @Around(value = "logPointCut()")
    public Object aroud(ProceedingJoinPoint joinPoint)throws Throwable{
        startTime.set(System.currentTimeMillis());
        //获取请求入参
        String methodArgs = getMethodArgs(joinPoint);
        String ip = UserContextHolder.getInstance().getIp();
        LogInfoEntity loginfo = new LogInfoEntity();
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        String requestURI = null;
        HttpServletRequest request = null;
        //从获取RequestAttributes中获取HttpServletRequest的信息
        if (requestAttributes != null){
            request = (HttpServletRequest)requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
            if (request != null){
                requestURI = request.getRequestURI();
                String userAgent = request.getHeader("user-agent");
                loginfo.setUerAgent(userAgent);
                if (userAgent.indexOf("Android") != -1 || userAgent.indexOf("iPhone") != -1 || userAgent.indexOf("iPad") != -1){
                    loginfo.setOperationTerminal(DepartCommonConstant.OperationTerminal.PHONE);
                }else {
                    //电脑
                    loginfo.setOperationTerminal(DepartCommonConstant.OperationTerminal.PC);
                }
            }
        }
        String operationName = "";
        String apiName = "";
        MethodSignature sign = (MethodSignature)joinPoint.getSignature();
        Method method = sign.getMethod();
        ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
        if (Objects.nonNull(apiOperation)){
            operationName = apiOperation.value();
        }
        Api apiAnnotation = joinPoint.getTarget().getClass().getAnnotations(Api.class);
        if (Objects.nonNull(apiAnnotation)){
            String[] tags = apiAnnotation.tags();
            apiName = StringUtils.join(tags,",");
        }
        Systemlog methodSystemlog =  method,getAnnnotation(Systemlog.class);
        boolean logToDios = Objects.nonNull(methodSystemlog) && methodSystemlog.accessToDios();
        SystemLog targetSystemLog = joinPoint.getTarget().getClass().getAnnotation(SystemLog.class);
        boolean targetAccessToDios = Objects.nonNull(targetSystemLog) && targetSystemLog.accessToDios();
        log.info("请求ip:{},请求uri:{},请求入参:{},请求方法:{},操作人:{}",ip,requestURI,
                methodArgs,apiName,operationName,UserContext.getInstance().getAccout()+"-"+UserContextHolder.getInstance().getUserName());
        //执行操作
        loginfo.setMenuName(apiName);
        loginfo.setLogType(Objects.nonNull(methodSystemlog) ? methodSystemlog.operationType():0);
        loginfo.setRequestUri(requestURI);
        Object result = null;
        try {
            result = joinPoint.proceed();
            long takeTime = System.currentTimeMillis() = startTime.get();
            loginfo.setTakeTime(takeTime);
            logService.insert(logInfo,result);
            startTime.remove();
            return result;
        }catch (Throwable e){
            long takeTime = System.currentTimeMillis() = startTime.get();
            loginfo.setTaskeTime(takeTime);
            loginfo.setStatus(false);
            logService.insert(loginfo,result);
            startTime.remove();
            if (e instanceof DepartException){
                throw e;
            }else if (e instanceof BadSqlGrammarException){
                Throwable rootCause = ((BadSqlGrammarException) e).getRootCause();
                throw new DepartException(DepartCommonConstant.NetStatus.ERROR_STRING,rootCause.getMessage());
            }else if (e instanceof NullPointerException){
                throw new DepartException(DepartCommonConstant.NetStatus.ERROR_STRING,"空指针异常");
            }else {
                throw new DepartException(DepartCommonConstant.NetStatus.ERROR_STRING,e.getMessage());
            }
        }
    }

    private String getMethodArgs(JoinPoint point){
        Object[] args = point.getArgs();
        if (args == null || args.length == 0){
            return "";
        }
        try{
            Map<String, Object> params = new HashMap<>();
            String[] parameterNames = ((MethodSignature) point.getSignature()).getParameterNames();
            for (int i=0;i<parameterNames.length;i++){
                Object arg = args[i];
                //过滤不能转换成JSON的参数
                if ((arg instanceof ServletRequest) || (arg instanceof ServletResponse)){
                    continue;
                }else if ((arg instanceof MultipartFile)){
                    arg = ((MultipartFile) arg).getOriginalFilename();
                }
                params.put(parameterNames[i],arg);
            }
            return JSON.toJSONString(params);
        }catch (Exception e){
            log.error("接口出入参数日志打印切面处理请求参数异常",e);
        }
        return Arrays.toString(args);
    }
}*/





























